package com.guangfeng.yql.comm.netty.initalizer;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.guangfeng.yql.comm.netty.NettyProperty;
import com.guangfeng.yql.comm.netty.verify.DataVerify;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.cors.CorsConfig;
import io.netty.handler.codec.http.cors.CorsConfigBuilder;
import io.netty.handler.codec.http.cors.CorsHandler;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class HttpInitializer extends BaseInitializer {

    @Override
    public void init(NettyProperty nettyProperty) {
        setNettyProperty(nettyProperty);
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin().allowNullOrigin().allowCredentials().build();

        ch.pipeline()
                .addLast(new HttpResponseEncoder())
                .addLast(new HttpRequestDecoder())
//                .addLast(new ChunkedWriteHandler())
//                .addLast(new HttpObjectAggregator(64 * 1024))
                .addLast(new CorsHandler(corsConfig))
                .addLast(new ChannelInboundHandlerAdapter() {
                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                        if (msg instanceof DefaultHttpRequest) {
                            DefaultHttpRequest request = (DefaultHttpRequest) msg;
                            String uri = request.uri();
                            if (!uri.startsWith(getNettyProperty().getPath())) {
                                ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND)).addListener(ChannelFutureListener.CLOSE);
                                return;
                            }
                        }
                        List<Class<? extends DataVerify>> list = getNettyProperty().getVerify();
                        if (CollUtil.isNotEmpty(list)) {
                            for (Class<? extends DataVerify> aClass : list) {
                                DataVerify verify = SpringUtil.getBean(aClass);
                                if (!verify.verify(ctx, msg)) {
                                    return;
                                }
                            }
                        }
                        super.channelRead(ctx, msg);
                    }
                })
                .addLast(super.getNettyProperty().getHandler().getName(), SpringUtil.getBean(super.getNettyProperty().getHandler()));
    }
}
